package com.fsbm.ctech.maxis.ebpsbackend;

import com.checkfree.isolutions.customer.persist.*;
import com.checkfree.isolutions.persist.*;
import com.checkfree.isolutions.statement.*;
import com.checkfree.isolutions.statement.persist.*;
import com.checkfree.isolutions.utility.*;
import com.checkfree.isolutions.admin.*;
import com.checkfree.isolutions.streaming.*;
import com.checkfree.isolutions.admin.ObjectId;

import java.io.File;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.Vector;
import java.util.Properties;


import java.io.*;
import java.text.*;
import java.util.*;
import java.util.Date;
import java.sql.*;

/**
 * Batch Program to write Notification required files. Reads objects from the CheckFree DB thru
 * API to build the CSV files. It will stream the CSV and will build the zip files for transfer.
 * Instantiates an FTP and telnet session with the SMTP Server to transfer files.
 * <p>
 * Maxis Backend Program - Deliver Bills in customers inbox for subscriptions or adhoc requests.
 *
 * @author Meau
 */

public class GenerateZipFileByStmts {
    static ConfigObject cfgObj = new ConfigObject();
    static int intFileSize = cfgObj.maxFileAmount;
    static String[][] strSubsArrayFileName = new String[intFileSize][intFileSize];

    public static void main(String argv[]) {
        String strFile="";
        for (int optind = 0; optind < argv.length; optind++) {
            if (argv[optind].toLowerCase().indexOf("-procfile") != -1) {
                strFile = argv[optind];
                strFile = strFile.substring(strFile.indexOf("=")+1);
            } else if (argv[optind].toLowerCase().startsWith("-h")) {
                printUsage();
                System.exit(1);
            } else {
                break;
            }
        }
        // Main Program Call
        startMain(strFile);
        System.exit(0);
    }

    // Start of sub-routines
    public static void startMain(String strFile) {
        java.util.Date startTime = new Date();
        java.util.Date startTransferTime = new Date();
        java.util.Date endTransferTime = new Date();
        // Start to call creation of CSV, PDF, body.txt, command file and zipping of files
        try{

            if((strFile.length() > 0)){
                runner(strFile);
            }

        	//  Start of Transfer Functionality //
        	java.util.Date endTime = new Date();

        	// Display start and end times of Execution //
        	cfgObj.write("\n-------------------------------------------------" +
        	             "\nStart of Execution : " + startTime +
        	             "\nEnd   of Execution : " + endTime, "GenerateZipFileByStmts");
        	} catch (Exception ex) {
        	    cfgObj.write("Process Name(runner)- " + ex.getClass() + " " + ex.getMessage(), "GenerateZipFileByStmts");}
    	}


    	// Start of runner sub-routines
    	public static void runner(String strFile) {
    	    try{

				ArrayList arrListExternalAcctKeys = new ArrayList();
				Vector vecStatementIds = new Vector();

				if(strFile.length() > 0){    // Subscription PDF Delivery (Main)
    	            arrListExternalAcctKeys = extractExternalAcctKeys(strFile.trim());
    	            cfgObj.write("Done with external acocunt key extraction for => " + strFile.trim(), "GenerateZipFileByStmts");

					vecStatementIds = getAllStmtIds(arrListExternalAcctKeys);


            	    // Start of generate zip file process
            	    int vSize = vecStatementIds.size();
            	    System.out.println("Size is....."+vecStatementIds.size());
            	    if(vSize>0){
						cfgObj.write("Starting file generation processes...","GenerateZipFileByStmts");
						strSubsArrayFileName = GenerateFiles(vecStatementIds);
	                    cfgObj.write("Initialize Packaging...", "GenerateZipFileByStmts");
						PrepareFiles.PackageSubsDeliveryFiles(strSubsArrayFileName);                 // Call to create body/command and zip package
                    } else {
                        cfgObj.write("Process Name(runner) - There are no Statements found or Delivery Subscriptions.","GenerateZipFileByStmts");
                    }// end if
				}// end if
			}catch (Exception ex) {
				cfgObj.write("Process Name(runner)- " + ex.getClass() + " " + ex.getMessage(),"DeliverErr");
			}//end try
		}// end class

    private static Vector getAllStmtIds(ArrayList arrExtAcctKeyString) throws Exception {

   		Connection connection = null;
        PreparedStatement pstmt = null;
        ResultSet rs= null;
        StringBuffer query = new StringBuffer();
        Vector vStatementIds = new Vector();
        Vector vector = new Vector();

        try{
      		Class.forName(cfgObj.databaseDriver);
      		connection = DriverManager.getConnection(cfgObj.databaseSourceName, cfgObj.databaseUserID, cfgObj.databasePassword);

      		if (connection!=null){
      		  query.append("SELECT A.EXTERNALACCOUNTKEY, S.INSTANCEID ,AD.EMAILADD FROM STATEMENT S,ACCOUNT A,ACCOUNTDETAILS AD ");
      		  query.append(" WHERE A.EXTERNALACCOUNTKEY=? AND A.ID=S.ACCOUNTID AND AD.EMAILDELIVERYSUBSCRIPTION='1' AND AD.EMAILADD IS NOT NULL ");
      		  query.append(" AND AD.ACCTID=A.EXTERNALACCOUNTKEY AND TO_CHAR(TO_DATE(S.STATEMENTDATE,'J'),'MMYYYY')= '122006' ");

      		  for(int i=0;i<arrExtAcctKeyString.size();i++){
				  String strExtAcctKey = (String)arrExtAcctKeyString.get(i);
				  System.out.println("Account external key is...."+strExtAcctKey);

                  // prepare the statement and bind parameter
                  pstmt = connection.prepareStatement(query.toString());
                  pstmt.setString(1,strExtAcctKey);

                  rs   = pstmt.executeQuery();
                  String stmtId = "";
                  //String acctId = "";
                  String acctExternalKey = "";

                  while (rs.next()){
					  System.out.println("Inside while rs....");
					  //setting account id,statement id,email address
					  StatementIdsDataBean stmtDataBean = new StatementIdsDataBean();
					  stmtDataBean.setData(rs.getString(1),rs.getString(2),rs.getString(3));

					  // add to vector
					  vector.addElement(stmtDataBean);
				  }// end while
			  pstmt.close();
			  rs.close();
			  }// end for

		  }// end if
	  }catch(Exception e){
		  throw new Exception("" + e);
	  }finally{
		  if(connection!=null){
			  connection.close();
		  }
		  if(rs!=null){
			  rs=null;
		  }
	  }// end try
	  System.out.println("Get all statement Ids has been successfully executed");
	  return vector;
  }// end method



		// GenerateFiles
		private static String[][] GenerateFiles(Vector vecStmtIds){
		    String[][] strFileName = new String[intFileSize][intFileSize];
		    String strFname="";
			int intCtr=0;
			int pos=0;

			FileOutputStream outstr = null;
		    InputStream instr   = null;
		    int intCommitCtr = 0;
		    boolean boolFirstLine = true;

		    StatementIdsDataBean stmtIdDataBean = null;
		    String strStmtId = "";

		    try{
				FileWriter fwFile = null;
				String amountDue="";
				int persisServerCtr = 0;
            	int intFileCtr=0;

				PersistServer.activate();

				for(int i=0;i<vecStmtIds.size();i++){
					if(persisServerCtr == 0) {
						cfgObj.write("Activating Persistent Server.....","GenerateZipFileByStmts");
						PersistServer.beginTransaction();
						cfgObj.write("Starting the transaction.....","GenerateZipFileByStmts");
					}

					if(intCtr==0 || intCtr==cfgObj.maxSubsRowPerCSV){
						System.out.println("counter is......"+intCtr);
					    DateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss'X'");
				        strFileName[0][intFileCtr] = cfgObj.pdfEmailFileList + formatter.format(new java.util.Date()) + intFileCtr;
				        strFname = strFileName[0][intFileCtr];
				        boolFirstLine = true;
				        intFileCtr++;
				        intCtr=0;
					}

					stmtIdDataBean = (StatementIdsDataBean)vecStmtIds.elementAt(i);

					AccountHome acctHome = AccountHomeImpl.singleton();                    // get account home
					StatementHome home = StatementHomeImpl.singleton();                  // get statement home

					strStmtId = stmtIdDataBean.getStmtId();
					int statementId = Integer.parseInt(strStmtId);        // convert string stmt Id to integer
					ObjectId objectId = new ObjectId(IClassId.STATEMENT, statementId);  // create an statement Object id based from the statement id string
		    	    com.checkfree.isolutions.statement.persist.Statement cfiStatement   = home.findById(objectId);                        // exract statement object
    	            Account accountObj = acctHome.findById(cfiStatement.getAccountId());
    	            //AcctDetails acctDetails = new AcctDetails();

		    	    // extract to string the ffg info for faster performance
		    	    String acctId = stmtIdDataBean.getAcctId();
		    	    String acctDeliveryEmail = stmtIdDataBean.getEmailAdd();
		    	    amountDue = getFormattedAmount(cfiStatement.getUserField2());
		    	    String accountName = cfiStatement.getUserField1();
		    	    String billingPeriod = new SimpleDateFormat("dd/MM/yyyy").format(cfiStatement.getDate());
		    	    accountName = accountName.replace(',', ' ');

		    	    cfgObj.write("Checking Statement ID: " + statementId + " Account :" + acctId,"GenerateZipFileByStmts");

		    	    pos = strFname.lastIndexOf("/");
		    	    fwFile = new FileWriter(strFname+".csv",true);

		    	    if(boolFirstLine){
						fwFile.write(cfgObj.emailHeader1 + "," + cfgObj.emailHeader2 + "," + cfgObj.emailHeader3 + "," + cfgObj.emailHeader4 + "," + cfgObj.emailHeader5 + "," + cfgObj.emailHeader6 + "," + cfgObj.emailHeader7);
						boolFirstLine = false;
					}

					fwFile.write("\n"+billingPeriod + "," + acctDeliveryEmail + "," + accountName + "," + acctId + "," + amountDue + ',' + billingPeriod + "," + strFname.substring(pos+1) + "." + statementId + "~" + acctId + ".pdf" );
					outstr        = new FileOutputStream(strFname + "." + statementId + "~" + acctId + ".pdf");
					byte[] buffer = new byte[262144];
					int size      = 0;
					instr         = cfiStatement.getExternalFormatData();          // actual downloading of file in pdf

	                persisServerCtr++;

	                if(persisServerCtr == 50) {
						// close transaction to avoid wasting memory
						cfgObj.write("Commiting transaction when ctr =50.......","GenerateZipFileByStmts");
						PersistServer.commitTransaction();
	                    persisServerCtr = 0;
	                }

					while ((size  = instr.read(buffer, 0, buffer.length)) != -1) {
						outstr.write(buffer, 0, size);
					}
					instr.close();
					outstr.flush();
					outstr.close();
					fwFile.close();

					cfgObj.write("Found StmtID : " + statementId + " Account :" + acctId + " ->" + acctDeliveryEmail, "GenerateZipFileByStmts");

					if(intCtr==cfgObj.maxSubsRowPerCSV-1){
						DBLog.createDeliveryRecord(strFname.substring(pos+1) + ".csv", cfgObj.maxSubsRowPerCSV,"SUBSCR");
					}
					intCtr++;

				}// end for
				if(intCtr<cfgObj.maxSubsRowPerCSV && intCtr>0){
					DBLog.createDeliveryRecord(strFname.substring(pos+1) + ".csv", intCtr,"SUBSCR");
				}

				if(persisServerCtr != 0) {
					cfgObj.write("Commiting transaction when ctr !=0.......","GenerateZipFileByStmts");
    	            PersistServer.commitTransaction();
    	        }

			}catch (Exception ex) {
				cfgObj.write("Process Name(execDeliverBySubscription)- for statement id(" +strStmtId+") - " + ex.getClass() + " " + ex.getMessage(), "GenerateZipFileByStmts");
			}finally {
				if (PersistServer.transactionIsActive()) {
					try {
						PersistServer.rollbackTransaction();
						cfgObj.write("Process Name(execDeliverBySubscription)- Rolling back all CheckFree transactions","GenerateZipFileByStmts");
					}catch (Exception e) {
						//ignore
					}
				}
			PersistServer.deactivate(true); //clean up with deactivate
			}// end try
			return strFileName;
		}// end method




    	// Extract the statementrun IDs from the billProcFile
    	public static ArrayList extractExternalAcctKeys(String fileName){
			System.out.println("File name is......"+fileName);
    	    String lineFileReader    = "";
    	    ArrayList runIds         = new ArrayList();
    	    try {
    	        RandomAccessFile raf = new RandomAccessFile(fileName, "rw");
    	        boolean lnvalue      = true;
    	        String line          = "";
    	        int iCount           = 0;
    	        String[] strAccounts = new String[1024];
    	        while (lnvalue){
    	            line = raf.readLine();
    	            if (line == null){                                         //when end of file
    	                lnvalue      = false; }
    	            else{
    	                    runIds.add(line);
    	            }
    	        }
    	        raf.close();
    	    }
    	    catch (Exception ex) {
    	        cfgObj.write("Process Name(extractExternalAcctKeys)- " + ex.getClass() + " " + ex.getMessage(),"GenerateZipFileByStmts");
    	    }
    	    return runIds;
    	}

    	public static void printUsage() {
    	      System.out.println("\nCopyright (c) 2002 FSBM CTech Sdn Bhd (427095-M).");
    	      System.out.println("All rights reserved.");
    	      System.out.println("\n\nUsage : deliver.sh [-DeliveryOptions=0|1|2] [-ProcFile=FILENAME]");
    	      System.out.println("or :");
    	      System.out.println("\tjava -server -Xms[HS] -Xmx[HS] -DBGROOT=/app/cfi Deliver");
    	      System.out.println("\t[-DeliveryOptions=0|1|2] [-ProcFile=FILENAME]");
    	      System.out.println("\n\nWhere:");
    	      System.out.println("\t -[FILENAME] where file.txt is the output of billproc");
    	      System.out.println("\t -[HS] Min and Max Heap Memory size allocation");
    	      System.out.println("\t -[0] Subscription and Adhoc requests(procFile param req'd)");
    	      System.out.println("\t -[1] Subscription only(procFile option req'd)");
    	      System.out.println("\t -[2] Adhoc request only");
    	      System.out.println("\n\tor java Deliver -h for help options");
    	      System.out.println("\tor deliver.sh -h for help options");
    	 }

    	public static String getFormattedAmount(String amountDue) {
    	            amountDue    = amountDue.replace(',',' ');
    	            StringTokenizer stAmountDue = new StringTokenizer(amountDue," ",false);
    	            amountDue    = "";
    	            while (stAmountDue.hasMoreElements()) amountDue += stAmountDue.nextElement();
    	    return amountDue;
    	}


	} // end class Deliver

	/* Use for debugging ... do not delete.
	        for (int i = 0; i < myFiles[1].length; i++){
	            System.out.println(myFiles[1][i]);
	        }
	 */

